package com.wuyi.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.wuyi.service.FileUploadService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author 曾川
 * @version 1.0.0
 * @ClassName FileUpload.java
 * @Description 上传实现类
 * @createTime 2021年11月11日 17:13:00
 */
@Service
public class FileUploadServiceImpl implements FileUploadService {

    public final static Logger logger = LoggerFactory.getLogger(FileUploadServiceImpl.class);


    //填写Bucket所在地域对应的Endpoint
    public final static String endpoint = "";
    public final static String ossHost = "";
    public final static String accessKeyId = "";
    public final static String accessKeySecret = "";
    public final static String bucketName = "";
    public final static String objectName = "";


    @Override
    public String upload(MultipartFile file, String userName, String uploadType) throws IOException {

        // 构建ossClient
        OSS ossClient = new OSSClientBuilder()
                .build(endpoint, accessKeyId, accessKeySecret);


        InputStream inputStream = file.getInputStream();

        String filesName = file.getOriginalFilename();
        //截取后缀名
        int fileOf = filesName.lastIndexOf(".");
        String fileType = filesName.substring(fileOf + 1);
        logger.info("-----------当前文件格式为：" + fileType);


        String myObjectName = objectName + "/" + userName + "/" +  uploadType + "/" + UUID.randomUUID() +"."+ fileType;

        ossClient.putObject(bucketName, myObjectName, inputStream);
        ossClient.shutdown();

        return myObjectName;
    }

    @Override
    public  String upload2(MultipartFile file, String userName, String uploadType) throws IOException {
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        String filesName = file.getOriginalFilename();
        //截取后缀名
        int fileOf = filesName.lastIndexOf(".");
        String fileType = filesName.substring(fileOf + 1);
        logger.info("-----------当前文件格式为：" + fileType);


        String myObjectName = objectName + "/" + userName + "/" +  uploadType + "/" + UUID.randomUUID() +"."+ fileType;


        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, myObjectName);

        // 初始化分片。
        InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
        // 返回uploadId，它是分片上传事件的唯一标识，您可以根据这个uploadId发起相关的操作，如取消分片上传、查询分片上传等。
        String uploadId = upresult.getUploadId();

        // partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
        List<PartETag> partETags = new ArrayList<PartETag>();
        // 计算文件有多少个分片。
        // 1MB
        final long partSize = 100 * 1024 * 1024L;
        // 我这里读取的是本地的一个文件
//        final File sampleFile = new File("");
//        long fileLength = sampleFile.length();
        long fileLength = file.getSize();
        int partCount = (int) (fileLength / partSize);
        if (fileLength % partSize != 0) {
            partCount++;
        }
        // 遍历分片上传。
        for (int i = 0; i < partCount; i++) {
            long startPos = i * partSize;
            long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
//            InputStream instream = new FileInputStream();
            InputStream instream = file.getInputStream();
            // 跳过已经上传的分片。
            instream.skip(startPos);
            UploadPartRequest uploadPartRequest = new UploadPartRequest();
            uploadPartRequest.setBucketName(bucketName);
            uploadPartRequest.setKey(myObjectName);
            uploadPartRequest.setUploadId(uploadId);
            uploadPartRequest.setInputStream(instream);
            // 设置分片大小。除了最后一个分片没有大小限制，其他的分片最小为100 KB。
            uploadPartRequest.setPartSize(curPartSize);
            // 设置分片号。每一个上传的分片都有一个分片号，取值范围是1~10000，如果超出这个范围，OSS将返回InvalidArgument的错误码。
            uploadPartRequest.setPartNumber(i + 1);
            // 每个分片不需要按顺序上传，甚至可以在不同客户端上传，OSS会按照分片号排序组成完整的文件。
            UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
            // 每次上传分片之后，OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
            partETags.add(uploadPartResult.getPartETag());
        }
        // 创建CompleteMultipartUploadRequest对象。
        // 在执行完成分片上传操作时，需要提供所有有效的partETags。OSS收到提交的partETags后，会逐一验证每个分片的有效性。当所有的数据分片验证通过后，OSS将把这些分片组合成一个完整的文件。
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(bucketName, myObjectName, uploadId, partETags);

        // 如果需要在完成文件上传的同时设置文件访问权限，请参考以下示例代码。
        // completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead);
        CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);

        // 关闭OSSClient。
        ossClient.shutdown();

        return myObjectName;

    }

    @Override
    public void download(String path, HttpServletResponse response) throws IOException {

        /*try {
            // 构建ossClient
            OSS ossClient = new OSSClientBuilder()
                    .build(endpoint, accessKeyId, accessKeySecret);
            OSSObject ossObject = ossClient.getObject(bucketName, path);
            String[] split = path.split("/");
            String name = split[split.length-1];
            int buffer = 1024 * 10;
            byte data[] = new byte[buffer];
            if (ossObject != null) {
                InputStream inputStream = ossObject.getObjectContent();
                // 文件名可以任意指定
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "iso-8859-1"));
//                response.addHeader("Content-Disposition","attachment;fileName=" +new String(name.getBytes("UTF-8"),"iso-8859-1"));

                int read;
                while ((read = inputStream.read(data)) != -1) {
                    response.getOutputStream().write(data, 0, read);
                }
                response.getOutputStream().flush();
                response.getOutputStream().close();
                ossObject.close();
            }

            return JSONResult.errorMsg("文件不存在");
        } catch (Exception e) {
            OSSException ee = (OSSException) e;
            e.printStackTrace();
            return JSONResult.errorMsg("下载失败");
        }*/

        //构建OSS，一般交给bean做，这里简单直接生成
        OSS ossClient = new OSSClientBuilder()
                .build(endpoint, accessKeyId, accessKeySecret);

        //获取bucketName，和 oss上文件的路径
        OSSObject ossObject = ossClient.getObject(bucketName, path);
        //截取图片名称
        String[] split = path.split("/");
        String name = split[split.length-1];
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "UTF-8"));
        // 读取文件内容
        BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        byte[] buffer = new byte[1024];
        int lenght;
        try {
            while ((lenght = in.read(buffer)) != -1) {
                out.write(buffer, 0, lenght);
            }
            out.flush();
        } catch (IOException e) {
            logger.error("Error occurred: {}", e.getMessage(), e);
        }

    }
}
